package com.megaspacevr.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.megaspacevr.entity.Bookings;
import com.megaspacevr.entity.PersonalInfo;
import com.megaspacevr.entity.TimeSlots;
import com.megaspacevr.entity.vo.BookingExportVO;
import com.megaspacevr.entity.vo.PageVO;
import com.megaspacevr.mapper.BookingsMapper;
import com.megaspacevr.service.BookingsService;
import com.megaspacevr.service.PersonalInfoService;
import com.megaspacevr.service.TimeSlotsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * <p>
 * 预约表-预约记录 服务实现类
 * </p>
 *
 * @author yezi
 * @since 2025-06-17
 */
@Slf4j
@Service
public class BookingsServiceImpl extends ServiceImpl<BookingsMapper, Bookings> implements BookingsService {

    @Autowired
    private TimeSlotsService timeSlotsService;

    @Autowired
    private PersonalInfoService personalInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createBooking(Bookings bookings) {
        log.info("开始创建预约，用户标识: {}, 电话: {}", bookings.getUserToken(), bookings.getContactPhone());
        
        try {
//            // 1. 检查用户是否已经预约过
//            if (hasUserBooked(bookings.getUserToken(), bookings.getContactPhone())) {
//                log.warn("用户已经预约过，无法重复预约");
//                return false;
//            }
//
            // 2. 检查时间段是否可用
            TimeSlots timeSlot = timeSlotsService.getById(bookings.getTimeSlotId());
            if (timeSlot == null || !timeSlot.getIsAvailable() || timeSlot.getIsLocked()) {
                log.warn("时间段不可用或已锁定");
                return false;
            }
            
            // 3. 检查是否还有剩余名额
            if (timeSlot.getBookedCount() >= timeSlot.getMaxCapacity()) {
                log.warn("时间段已满，无法预约");
                return false;
            }
            
            // 4. 处理个人信息
            PersonalInfo personalInfo = personalInfoService.getPersonalInfoByPhone(bookings.getContactPhone());
            if (personalInfo == null) {
                // 创建新的个人信息记录
                personalInfo = new PersonalInfo();
                personalInfo.setUserToken(bookings.getUserToken());
                personalInfo.setName(bookings.getContactName());
                personalInfo.setPhone(bookings.getContactPhone());
                personalInfo.setIsDefault(true);
                personalInfo.setCreatedAt(LocalDateTime.now());
                personalInfo.setUpdatedAt(LocalDateTime.now());
                
                // 从备注中提取个人信息（如果有的话）
                if (bookings.getNotes() != null && !bookings.getNotes().isEmpty()) {
                    extractPersonalInfoFromNotes(personalInfo, bookings.getNotes());
                }
                
                // 从特殊需求中提取个人信息（如果有的话）
                if (bookings.getSpecialRequirements() != null && !bookings.getSpecialRequirements().isEmpty()) {
                    extractPersonalInfoFromSpecialRequirements(personalInfo, bookings.getSpecialRequirements());
                }
                
                personalInfoService.save(personalInfo);
                log.info("创建新的个人信息记录，ID: {}", personalInfo.getId());
            } else {
                log.info("使用已存在的个人信息记录，ID: {}", personalInfo.getId());
            }
            
            // 5. 设置预约信息
            bookings.setPersonalInfoId(personalInfo.getId());
            bookings.setBookingNumber(generateBookingNumber());
            bookings.setBookingDate(timeSlot.getSlotDate());
            bookings.setBookingTimeStart(timeSlot.getStartTime());
            bookings.setBookingTimeEnd(timeSlot.getEndTime());
            bookings.setPeriodName(timeSlot.getPeriodName());
            bookings.setStatus("已预约");
            bookings.setCreatedAt(LocalDateTime.now());
            bookings.setUpdatedAt(LocalDateTime.now());
            
            // 6. 保存预约记录
            boolean saveResult = save(bookings);
            if (!saveResult) {
                log.error("保存预约记录失败");
                return false;
            }
            
            // 7. 更新时间段预约人数
            boolean updateResult = timeSlotsService.updateBookedCount(bookings.getTimeSlotId());
            if (!updateResult) {
                log.error("更新时间段预约人数失败");
                throw new RuntimeException("更新时间段预约人数失败");
            }
            
            log.info("预约创建成功，预约编号: {}", bookings.getBookingNumber());
            return true;
            
        } catch (Exception e) {
            log.error("创建预约时发生异常", e);
            throw e;
        }
    }

    /**
     * 从备注中提取个人信息
     */
    private void extractPersonalInfoFromNotes(PersonalInfo personalInfo, String notes) {
        try {
            String[] parts = notes.split("，");
            for (String part : parts) {
                if (part.startsWith("性别：")) {
                    personalInfo.setGender(part.replace("性别：", ""));
                } else if (part.startsWith("年龄：")) {
                    try {
                        personalInfo.setAge(Integer.parseInt(part.replace("年龄：", "")));
                    } catch (NumberFormatException e) {
                        log.warn("年龄格式错误: {}", part);
                    }
                } else if (part.startsWith("学历：")) {
                    personalInfo.setEducation(part.replace("学历：", ""));
                }
            }
        } catch (Exception e) {
            log.warn("从备注中提取个人信息失败", e);
        }
    }

    /**
     * 从特殊需求中提取个人信息
     */
    private void extractPersonalInfoFromSpecialRequirements(PersonalInfo personalInfo, String specialRequirements) {
        try {
            if (specialRequirements.startsWith("职业：")) {
                personalInfo.setOccupation(specialRequirements.replace("职业：", ""));
            }
        } catch (Exception e) {
            log.warn("从特殊需求中提取个人信息失败", e);
        }
    }

    @Override
    public boolean hasUserBooked(String userToken, String contactPhone) {
        QueryWrapper<Bookings> queryWrapper = new QueryWrapper<>();
        queryWrapper.and(wrapper -> 
            wrapper.eq("user_token", userToken)
                   .or()
                   .eq("contact_phone", contactPhone)
        );
        queryWrapper.eq("status", "已预约");
        
        long count = count(queryWrapper);
        log.info("用户预约检查结果 - userToken: {}, phone: {}, count: {}", userToken, contactPhone, count);
        
        return count > 0;
    }

    @Override
    public String generateBookingNumber() {
        // 格式：VR + 年月日 + 时分秒 + 3位随机数
        String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        int random = (int) (Math.random() * 1000);
        String bookingNumber = "VR" + dateTime + String.format("%03d", random);
        
        log.info("生成预约编号: {}", bookingNumber);
        return bookingNumber;
    }

    @Override
    public List<Bookings> getUserBookings(String userToken) {
        log.info("查询用户预约记录 - userToken: {}", userToken);
        
        try {
            QueryWrapper<Bookings> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_token", userToken)
                       .orderByDesc("created_at"); // 按创建时间倒序排列
            
            List<Bookings> bookings = list(queryWrapper);
            log.info("用户预约记录查询完成，共找到 {} 条记录", bookings.size());
            
            return bookings;
        } catch (Exception e) {
            log.error("查询用户预约记录失败", e);
            throw new RuntimeException("查询用户预约记录失败", e);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelBooking(Long bookingId, String userToken) {
        log.info("取消预约 - bookingId: {}, userToken: {}", bookingId, userToken);
        
        try {
            // 1. 查询预约记录
            Bookings booking = getById(bookingId);
            if (booking == null) {
                log.warn("预约记录不存在 - bookingId: {}", bookingId);
                return false;
            }
            
            // 2. 验证用户权限
            if (!userToken.equals(booking.getUserToken())) {
                log.warn("用户无权限取消此预约 - bookingId: {}, userToken: {}", bookingId, userToken);
                return false;
            }
            
            // 3. 检查预约状态
            if (!"已预约".equals(booking.getStatus())) {
                log.warn("预约状态不允许取消 - bookingId: {}, status: {}", bookingId, booking.getStatus());
                return false;
            }
            
            // 4. 更新预约状态
            UpdateWrapper<Bookings> updateWrapper = new UpdateWrapper<>();
            updateWrapper.eq("id", bookingId)
                        .set("status", "已取消")
                        .set("updated_at", LocalDateTime.now());
            
            boolean updateResult = update(updateWrapper);
            if (!updateResult) {
                log.error("更新预约状态失败 - bookingId: {}", bookingId);
                return false;
            }
            
            // 5. 减少时间段预约人数
            boolean decreaseResult = timeSlotsService.decreaseBookedCount(booking.getTimeSlotId());
            if (!decreaseResult) {
                log.error("减少时间段预约人数失败 - timeSlotId: {}", booking.getTimeSlotId());
                throw new RuntimeException("减少时间段预约人数失败");
            }
            
            log.info("预约取消成功 - bookingId: {}", bookingId);
            return true;
            
        } catch (Exception e) {
            log.error("取消预约时发生异常 - bookingId: {}", bookingId, e);
            throw e;
        }
    }

    @Override
    public PageVO<BookingExportVO> getBookingsForAdminWithFullInfo(Integer pageNum, Integer pageSize, String searchText, 
                                                                  String startDate, String endDate, String status, 
                                                                  String periodName, String sortType) {
        log.info("管理员查询完整预约列表 - 页码: {}, 页大小: {}, 搜索: {}", pageNum, pageSize, searchText);
        
        PageVO<BookingExportVO> pageVO = new PageVO<>();
        PageHelper.startPage(pageNum, pageSize);
        
        List<BookingExportVO> bookings = baseMapper.getBookingsForExport(searchText, startDate, endDate, 
                                                                        status, periodName, sortType);
        Page<BookingExportVO> page = (Page<BookingExportVO>) bookings;
        pageVO.setTotal(page.getTotal());
        pageVO.setItems(page.getResult());
        
        log.info("管理员完整预约列表查询完成，共 {} 条记录", page.getTotal());
        return pageVO;
    }

    @Override
    public List<BookingExportVO> getBookingsForExport(String searchText, String startDate, String endDate, 
                                                     String status, String periodName, String sortType) {
        log.info("管理员导出完整预约数据 - 搜索: {}", searchText);
        
        List<BookingExportVO> bookings = baseMapper.getBookingsForExport(searchText, startDate, endDate, 
                                                                        status, periodName, sortType);
        log.info("管理员导出完整预约数据完成，共 {} 条记录", bookings.size());
        return bookings;
    }
}
